home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / common / recipe.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  8KB  |  334 lines

  1.  
  2.  
  3. /* Basic stuff for use with the alchemy code. Clearly some of this stuff
  4.  * could go into server/alchemy, but I left it here just in case it proves
  5.  * more generally useful. 
  6.  *
  7.  * Nov 1995 - file created by b.t. thomas@astro.psu.edu 
  8.  */
  9.  
  10.  
  11. /* Our definition of 'formula' is any product of an alchemical process.
  12.  * Ingredients are just comma delimited list of archetype (or object) 
  13.  * names. 
  14.  */
  15.  
  16. /* Example 'formula' entry in libdir/formulae:
  17.  *     Object transparency
  18.  *    chance 10
  19.  *    ingred dust of beholdereye,gem
  20.  *    arch potion_generic
  21.  */
  22.  
  23. #include <global.h>
  24. #include <object.h>
  25. #include <ctype.h>
  26.  
  27. static recipelist *formulalist;
  28.  
  29. static recipelist *init_recipelist() {
  30.   recipelist *tl = (recipelist *) malloc(sizeof(recipelist));
  31.   if(tl==NULL)
  32.     fatal(OUT_OF_MEMORY);
  33.   tl->total_chance=0;
  34.   tl->number=0;
  35.   tl->items=NULL;
  36.   tl->next=NULL;
  37.   return tl;
  38. }
  39.  
  40. recipe *get_empty_formula() {
  41.   recipe *t = (recipe *) malloc(sizeof(recipe));
  42.   if(t==NULL)
  43.     fatal(OUT_OF_MEMORY);
  44.   t->chance = 0;
  45.   t->index = 0;
  46.   t->transmute = 0;
  47.   t->title = NULL;
  48.   t->arch_name = NULL;
  49.   t->ingred = NULL;
  50.   t->next=NULL;
  51.   return t;
  52. }
  53.  
  54. /* get_formulalist() - returns pointer to the formula list */
  55.  
  56. recipelist * get_formulalist ( int i ) {
  57.   recipelist *fl=formulalist;
  58.   int number=i;
  59.  
  60.   while(fl && number>1) { 
  61.          if(!(fl=fl->next)) break;
  62.          number--;
  63.      }   
  64.   return fl;
  65. }
  66.  
  67. /*
  68.  * init_formulae() - Builds up the lists of formula from the file in 
  69.  * the libdir. -b.t. 
  70.  */
  71.  
  72. void init_formulae() {
  73.   static int has_been_done=0;
  74.   FILE *fp;
  75.   char filename[MAX_BUF], buf[MAX_BUF], *cp, *next;
  76.   recipe *formula=NULL;
  77.   recipelist *fl=init_recipelist();
  78.   linked_char *tmp;
  79.   int value, comp;
  80.  
  81.   if(!formulalist) formulalist = fl;
  82.  
  83.   if (has_been_done) return;
  84.   else has_been_done = 1;
  85.  
  86.   LOG(llevDebug, "Reading alchemical formulae...");
  87.   sprintf(filename, "%s/formulae", LibDir);
  88.   if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
  89.     LOG(llevError, "Can't open %s.\n", filename);
  90.     return;
  91.   }
  92.  
  93.   while (fgets(buf, MAX_BUF, fp)!=NULL) {
  94.     if (*buf=='#') continue;
  95.     if((cp=strchr(buf,'\n'))!=NULL)
  96.       *cp='\0';
  97.     cp=buf;
  98.     while(*cp==' ') /* Skip blanks */
  99.       cp++;
  100.  
  101.     if (!strncmp(cp, "Object", 6)) {
  102.       formula=get_empty_formula();
  103.       formula->title = add_string(strchr(cp,' ') + 1);
  104.     }
  105.     else if (sscanf(cp, "trans %d", &value)) {
  106.         formula->transmute = (uint16) value;
  107.     }
  108.     else if (sscanf(cp, "chance %d", &value)) {
  109.         formula->chance = (uint16) value;
  110.     }
  111.     else if (!strncmp(cp, "ingred",6)) {
  112.       int numb_ingred = 1;
  113.       cp = strchr(cp,' ') + 1;
  114.       do {
  115.         if ((next=strchr(cp,','))!=NULL)
  116.           {*(next++) = '\0'; numb_ingred++;}
  117.         tmp = (linked_char*) malloc(sizeof(linked_char));
  118.         tmp->name = add_string(cp);
  119.         tmp->next = formula->ingred;
  120.         formula->ingred = tmp;
  121.     /* each ingredient's ASCII value is coadded. Later on this 
  122.       * value will be used allow us to search the formula lists 
  123.      * quickly for the right recipe. 
  124.      */ 
  125.     formula->index += strtoint(cp);
  126.       } while ((cp=next)!=NULL);
  127.       /* now find the correct (# of ingred ordered) formulalist */
  128.       fl=formulalist;
  129.       while(numb_ingred!=1) {
  130.     if(!fl->next)
  131.       fl->next = init_recipelist();
  132.     fl = fl->next;
  133.         numb_ingred--;
  134.       }
  135.       fl->total_chance += formula->chance;
  136.       fl->number++;
  137.       formula->next = fl->items; 
  138.       fl->items = formula;
  139.     } else if (!strncmp(cp, "arch",4)) { 
  140.         formula->arch_name = add_string(strchr(cp,' ')+1);
  141.         (void) check_recipe(formula);
  142.     } else
  143.         LOG(llevError,"Unknown input in file %s: %s\n", filename, buf);
  144.   }
  145.  
  146.   close_and_delete(fp, comp);
  147.  
  148. #ifdef DUMP_SWITCHES
  149.   if (dump_monsters == 7) {
  150.     dump_alchemy();
  151.     exit(0);
  152.   } 
  153.   if (dump_monsters == 8) {
  154.     dump_prod_val_vs_cost();
  155.     exit(0);
  156.   }
  157. #endif
  158. }
  159.  
  160. /* Borrowed (again) from the artifacts code for this  */
  161.  
  162. void dump_alchemy( void ) {
  163.   recipelist *fl=formulalist;
  164.   recipe *formula=NULL;
  165.   linked_char *next;
  166.   int num_ingred=1;
  167.  
  168.   fprintf(logfile, "\n");
  169.   while(fl) { 
  170.     fprintf(logfile, "\n Formulae with %d ingredient%s  %d Formulae with total_chance=%d\n", 
  171.     num_ingred, num_ingred>1?"s.":".",fl->number,fl->total_chance);
  172.     for (formula=fl->items; formula!=NULL; formula=formula->next) {
  173.       artifact *art=NULL;
  174.       archetype *at=NULL;
  175.       char buf[MAX_BUF], *string;
  176.       
  177.       string=strtok(formula->arch_name,",");
  178.       while(string) { 
  179.     if((at=find_archetype(string))!=NULL) { 
  180.           art = locate_recipe_artifact(formula);
  181.           if (!art && strcmp(formula->title,"NONE")) 
  182.         LOG(llevError,"Formula %s has no artifact\n",formula->title);
  183.       else {
  184.          if(strcmp(formula->title,"NONE"))
  185.                 sprintf(buf,"%s of %s",string,formula->title);
  186.          else
  187.                 sprintf(buf,"%s",string);
  188.              fprintf(logfile,"%-30s(%d) bookchance %3d  ",buf,formula->index,
  189.         formula->chance);
  190.              fprintf(logfile,"\n");
  191.              if (formula->ingred !=NULL) {
  192.         int nval=0,tval=0;
  193.                 fprintf(logfile,"\tIngred: ");
  194.                 for (next=formula->ingred; next!=NULL; next=next->next) { 
  195.           if(nval!=0) fprintf(logfile,","); 
  196.                   fprintf(logfile,"%s(%d)",next->name,(nval=strtoint(next->name)));
  197.           tval += nval;
  198.         }
  199.                 fprintf(logfile,"\n");
  200.         if(tval!=formula->index) fprintf(logfile, "WARNING:ingredient list and formula values not equal.\n");
  201.              }  
  202.       }
  203.     } else 
  204.        LOG(llevError,"Can't find archetype:%s for formula %s\n", string,
  205.         formula->title); 
  206.     string = strtok(NULL,",");
  207.       }
  208.     }  
  209.   fprintf(logfile,"\n");
  210.   fl = fl->next;
  211.   num_ingred++;
  212.   }
  213. }
  214.  
  215. void dump_prod_val_vs_cost( void ) {
  216.  
  217.  
  218.  
  219. }
  220.  
  221. recipe *get_first_recipe() {
  222.   recipelist *fl=formulalist;
  223.   recipe *formula=fl->items;
  224.  
  225.   return formula;
  226. }
  227.  
  228. char * ingred_name (char *name) {
  229.   char *cp=name;
  230.  
  231.   if(atoi(cp)) cp = strchr(cp,' ') + 1;
  232.   return cp;
  233. }
  234.  
  235. /* strtoint() - we use this to convert buf into an integer
  236.  * equal to the coadded sum of the (lowercase) character 
  237.  * ASCII values in buf (times prepended integers).
  238.  */
  239.  
  240. int strtoint (char *buf) {
  241.   char *cp = ingred_name(buf);
  242.   int val=0, len=strlen(cp), mult=numb_ingred(buf);
  243.  
  244.   while (len) { 
  245.     val += tolower(*cp);
  246.     cp++; len--;
  247.   }
  248.   return val*mult;
  249. }
  250.  
  251. /* check_recipe() - makes sure we actually have the requested artifact 
  252.  * and archetype. */
  253.  
  254. int check_recipe(recipe *rp) {
  255.   archetype *at;
  256.  
  257.     if((at=find_archetype(rp->arch_name))!=NULL) { 
  258.           artifact *art=locate_recipe_artifact(rp);
  259.           if (!art && strcmp(rp->title,"NONE")) {
  260.         LOG(llevError,"\n WARNING: Formula %s of %s has no artifact.\n",
  261.                 rp->arch_name,rp->title); 
  262.         return 0;
  263.       }
  264.     } else { 
  265.            LOG(llevError,"\n WARNING: Can't find archetype:%s for formula:%s\n", 
  266.                 rp->arch_name,rp->title); 
  267.        return 0;
  268.     }
  269.    
  270.     return 1;
  271. }
  272.  
  273. artifact * locate_recipe_artifact(recipe *rp) {
  274.    object *item=get_archetype(rp->arch_name);
  275.    artifactlist *at=NULL;
  276.    artifact *art=NULL;
  277.  
  278.    if(!item) return (artifact *) NULL; 
  279.  
  280.    if((at=find_artifactlist(item->type)))
  281.       for(art=at->items;art;art=art->next)
  282.           if(!strcmp(art->item->name,rp->title)) break;
  283.  
  284.    free_object(item);
  285.  
  286.    return art;
  287. }
  288.  
  289. int numb_ingred (char *buf) {
  290.   int numb;
  291.  
  292.   if((numb=atoi(buf))) return numb;
  293.   else return 1;
  294. }
  295.  
  296. recipelist * get_random_recipelist ( void ) {
  297.   recipelist *fl=NULL;
  298.   int number=0,roll=0;
  299.  
  300.      /* first, determine # of recipelist we have */
  301.      for(fl=get_formulalist(1);fl;fl=fl->next) number++;
  302.  
  303.      /* now, randomly choose one */
  304.      if(number>0) roll=RANDOM()%number;
  305.  
  306.      fl=get_formulalist(1);
  307.      while(roll && fl) {
  308.         if(fl->next) fl = fl->next;
  309.         else break;
  310.         roll--;
  311.      }   
  312.      if(!fl) /* failed! */
  313.         LOG(llevError,"get_random_recipelist(): no recipelists found!\n");
  314.      else if(fl->total_chance==0) fl=get_random_recipelist();
  315.  
  316.      return fl;
  317. }
  318.  
  319. recipe * get_random_recipe ( recipelist *rpl ) {
  320.   recipelist *fl=rpl;
  321.   recipe *rp=NULL;
  322.   int r=0;
  323.  
  324.   /* looks like we have to choose a random one */ 
  325.   if(fl==NULL) if((fl=get_random_recipelist())==NULL) return rp;
  326.  
  327.   r=RANDOM()%fl->total_chance;
  328.   for (rp=fl->items;rp;rp=rp->next) {
  329.       r -= rp->chance;
  330.       if (r<0) break;
  331.   }
  332.   return rp;
  333. }
  334.